home *** CD-ROM | disk | FTP | other *** search
/ Aminet 30 / Aminet 30 (1999)(Schatztruhe)[!][Apr 1999].iso / Aminet / dev / cross / GBDK-2.0-src.lha / GBDK / link / lkmain.c < prev    next >
C/C++ Source or Header  |  1999-02-07  |  29KB  |  1,405 lines

  1. /* lkmain.c */
  2.  
  3. /*
  4.  * (C) Copyright 1989-1995
  5.  * All Rights Reserved
  6.  *
  7.  * Alan R. Baldwin
  8.  * 721 Berkeley St.
  9.  * Kent, Ohio  44240
  10.  */
  11.  
  12. /*
  13.  * Extensions: P. Felber
  14.  */
  15.  
  16. #include <stdio.h>
  17. #include <stdlib.h>
  18. #include <string.h>
  19. //#include <alloc.h>
  20. #include "aslink.h"
  21.  
  22. /*)Module    lkmain.c
  23.  *
  24.  *    The module lkmain.c contains the functions which
  25.  *    (1) input the linker options, parameters, and specifications
  26.  *    (2) perform a two pass link
  27.  *    (3) produce the appropriate linked data output and/or
  28.  *        link map file and/or relocated listing files.
  29.  *
  30.  *    lkmain.c contains the following functions:
  31.  *        FILE *    afile(fn,ft,wf)
  32.  *        VOID    bassav()
  33.  *        VOID    gblsav()
  34.  *        VOID    link()
  35.  *        VOID    lkexit()
  36.  *        VOID    main(argc,argv)
  37.  *        VOID    map()
  38.  *        int    parse()
  39.  *        VOID    setbas()
  40.  *        VOID    setgbl()
  41.  *        VOID    usage()
  42.  *
  43.  *    lkmain.c contains the following local variables:
  44.  *        char *    usetext[]    array of pointers to the
  45.  *                    command option tect lines
  46.  *
  47.  */
  48.  
  49. /*)Function    VOID    main(argc,argv)
  50.  *
  51.  *        int    argc        number of command line arguments + 1
  52.  *        char *    argv[]        array of pointers to the command line
  53.  *                    arguments
  54.  *
  55.  *    The function main() evaluates the command line arguments to
  56.  *    determine if the linker parameters are to input through 'stdin'
  57.  *    or read from a command file.  The functiond getline() and parse()
  58.  *    are to input and evaluate the linker parameters.  The linking process
  59.  *    proceeds by making the first pass through each .rel file in the order
  60.  *    presented to the linker.  At the end of the first pass the setbase(),
  61.  *    lnkarea(), setgbl(), and symdef() functions are called to evaluate
  62.  *    the base address terms, link all areas, define global variables,
  63.  *    and look for undefined symbols.  Following these routines a linker
  64.  *    map file may be produced and the linker output files may be opened.
  65.  *    The second pass through the .rel files will output the linked data
  66.  *    in one of the four supported formats.
  67.  *
  68.  *    local variables:
  69.  *        char *    p        pointer to an argument string
  70.  *        int    c        character from argument string
  71.  *        int    i        loop counter
  72.  *
  73.  *    global variables:
  74.  *                     text line in ib[]
  75.  *        lfile    *cfp        The pointer *cfp points to the
  76.  *                     current lfile structure
  77.  *        char    ctype[]        array of character types, one per
  78.  *                     ASCII character
  79.  *        lfile    *filep         The pointer *filep points to the
  80.  *                     beginning of a linked list of
  81.  *                     lfile structures.
  82.  *        head    *hp        Pointer to the current
  83.  *                     head structure
  84.  *        char    ib[NINPUT]    .rel file text line
  85.  *        char    *ip        pointer into the .rel file
  86.  *        lfile    *linkp        pointer to first lfile structure
  87.  *                     containing an input .rel file
  88.  *                     specification
  89.  *        int    lkerr        error flag
  90.  *        int    mflag        Map output flag
  91.  *        int    oflag        Output file type flag
  92.  *        FILE    *ofp        Output file handle
  93.  *                     for word formats
  94.  *        FILE    *ofph        Output file handle
  95.  *                     for high byte format
  96.  *        FILE    *ofpl        Output file handle
  97.  *                     for low byte format
  98.  *        int    pass        linker pass number
  99.  *        int    pflag        print linker command file flag
  100.  *        int    radix        current number conversion radix
  101.  *        FILE    *sfp        The file handle sfp points to the
  102.  *                     currently open file
  103.  *        lfile    *startp        asmlnk startup file structure
  104.  *        FILE *    stdin        c_library
  105.  *        FILE *    stdout        c_library
  106.  *
  107.  *    functions called:
  108.  *        FILE *    afile()        lkmain.c
  109.  *        int    fclose()    c_library
  110.  *        int    fprintf()    c_library
  111.  *        int    getline()    lklex.c
  112.  *        VOID    library()    lklibr.c
  113.  *        VOID    link()        lkmain.c
  114.  *        VOID    lkexit()    lkmain.c
  115.  *        VOID    lnkarea()    lkarea.c
  116.  *        VOID    map()        lkmain.c
  117.  *        VOID    new()        lksym.c
  118.  *        int    parse()        lkmain.c
  119.  *        VOID    reloc()        lkreloc.c
  120.  *        VOID    search()    lklibr.c
  121.  *        VOID    setbas()    lkmain.c
  122.  *        VOID    setgbl()    lkmain.c
  123.  *        VOID    symdef()    lksym.c
  124.  *        VOID    usage()        lkmain.c
  125.  *
  126.  *    side effects:
  127.  *        Completion of main() completes the linking process
  128.  *        and may produce a map file (.map) and/or a linked
  129.  *        data files (.ihx or .s19) and/or one or more
  130.  *        relocated listing files (.rst).
  131.  */
  132.  
  133. #ifdef SDK
  134. int binary = 0;
  135. #endif /* SDK */
  136. #ifdef GAMEBOY
  137. char *default_basep[] = {
  138.   "_CODE=0x0200",
  139.   "_BSS=0xC0A0",
  140.   NULL
  141. };
  142.  
  143. char *default_globlp[] = {
  144.   /* DMA transfer must start at multiples of 0x100 */
  145.   ".OAM=0xC000",
  146.   ".STACK=0xE000",
  147.   ".refresh_OAM=0xFF80",
  148.  
  149.   ".init=0x0000",
  150.  
  151.   NULL
  152. };
  153. #endif /* GAMEBOY */
  154.  
  155. VOID
  156. main(int argc,char *argv[])
  157. {
  158.     register char *p;
  159.     register c, i;
  160.  
  161. #ifdef GAMEBOY
  162.     nb_rom_banks = 2;
  163.     nb_ram_banks = 0;
  164.     mbc_type = 0;
  165.     symflag=0;
  166.  
  167.     for(i = 0; default_basep[i] != NULL; i++) {
  168.         if(basep == NULL) {
  169.             basep = (struct base *)new(sizeof(struct base));
  170.             bsp = basep;
  171.         } else {
  172.             bsp->b_base = (struct base *)new(sizeof(struct base));
  173.             bsp = bsp->b_base;
  174.         }
  175.         bsp->b_strp = default_basep[i];
  176.     }
  177.     for(i = 0; default_globlp[i] != NULL; i++) {
  178.         if(globlp == NULL) {
  179.             globlp = (struct globl *)new(sizeof(struct globl));
  180.             gsp = globlp;
  181.         } else {
  182.             gsp->g_globl = (struct globl *)new(sizeof(struct globl));
  183.             gsp = gsp->g_globl;
  184.         }
  185.         gsp->g_strp = default_globlp[i];
  186.     }
  187. #endif /* GAMEBOY */
  188. #ifndef SDK
  189.     fprintf(stdout, "\n");
  190. #endif /* SDK */
  191.  
  192.     startp = (struct lfile *) new (sizeof (struct lfile));
  193.  
  194.     pflag = 1;
  195.     for (i=1; i<argc; ++i) {
  196.         p = argv[i];
  197.         if (*p == '-') {
  198.             while (ctype[c = *(++p)] & LETTER) {
  199.                 switch(c) {
  200.  
  201.                 case 'c':
  202.                 case 'C':
  203.                     startp->f_type = F_STD;
  204.                     break;
  205.  
  206.                 case 'f':
  207.                 case 'F':
  208.                     startp->f_type = F_LNK;
  209.                     break;
  210.                     
  211.                 case 'n':
  212.                 case 'N':
  213.                     pflag = 0;
  214.                     break;
  215.  
  216.                 case 'p':
  217.                 case 'P':
  218.                     pflag = 1;
  219.                     break;
  220.  
  221.                 default:
  222.                     usage();
  223.                 }
  224.             }
  225.  
  226. #ifdef SDK
  227.             if(c == '-') {
  228.                 startp->f_type = F_CMD;
  229.                 startp->f_idp = (char *)&argv[i+1];
  230.                 break;
  231.             }
  232. #endif /* SDK */
  233.  
  234.         } else {
  235.             if (startp->f_type == F_LNK) {
  236.                 startp->f_idp = p;
  237.             }
  238.         }
  239.     }
  240.     if (startp->f_type == NULL)
  241.         usage();
  242.     if (startp->f_type == F_LNK && startp->f_idp == NULL)
  243.         usage();
  244. #ifdef SDK
  245.     if (startp->f_type == F_CMD && startp->f_idp == NULL)
  246.         usage();
  247. #endif /* SDK */
  248.  
  249.     cfp = NULL;
  250.     sfp = NULL;
  251.     filep = startp;
  252.     while (1) {
  253.         ip = ib;                    
  254.         if (getline() == 0)
  255.             break;
  256.         if (pflag && sfp != stdin)
  257.             fprintf(stdout, "%s\n", ip);
  258.         if (*ip == NULL || parse())
  259.             break;
  260.     }
  261.     if (sfp)
  262.         fclose(sfp);
  263.     if (linkp == NULL)
  264.         usage();
  265. #ifdef SDK
  266.     if (linkp->f_flp == NULL)
  267.         usage();
  268. #endif /* SDK */
  269.  
  270. #ifdef GAMEBOY
  271.     for(i = 1; i < nb_rom_banks; i++) {
  272.         bsp->b_base = (struct base *)new(sizeof(struct base));
  273.         bsp = bsp->b_base;
  274.         bsp->b_strp = (char *)malloc(18);
  275.         sprintf(bsp->b_strp, "_CODE_%d=0x4000", i);
  276.     }
  277.     for(i = 0; i < nb_ram_banks; i++) {
  278.         bsp->b_base = (struct base *)new(sizeof(struct base));
  279.         bsp = bsp->b_base;
  280.         bsp->b_strp = (char *)malloc(18);
  281.         sprintf(bsp->b_strp, "_BSS_%d=0xA000", i);
  282.     }
  283. #endif /* GAMEBOY */
  284.  
  285.     syminit();
  286.     for (pass=0; pass<2; ++pass) {
  287.         cfp = NULL;
  288.         sfp = NULL;
  289. #ifdef SDK
  290.         filep = linkp->f_flp;
  291. #else /* SDK */
  292.         filep = linkp;
  293. #endif /* SDK */
  294.         hp = NULL;
  295.         radix = 10;
  296.  
  297.         while (getline()) {
  298.             ip = ib;
  299.             link();
  300.         }
  301.         if (pass == 0) {
  302.             /*
  303.              * Search libraries for global symbols
  304.              */
  305.             search();
  306.             /*
  307.              * Set area base addresses.
  308.              */
  309.             setbas();
  310.             /*
  311.              * Link all area addresses.
  312.              */
  313.             lnkarea();
  314.             /*
  315.              * Process global definitions.
  316.              */
  317.             setgbl();
  318.             /*
  319.              * Check for undefined globals.
  320.              */
  321.             symdef(stderr);
  322. #ifdef SDK
  323.             if (symflag) 
  324.                 sym();
  325. #endif
  326.             /*
  327.              * Output Link Map.
  328.              */
  329.             if (mflag)
  330.                 map();
  331.             /*
  332.              * Open output file
  333.              */
  334.             if (oflag == 1) {
  335. #ifdef SDK
  336.                 ofp = afile(linkp->f_idp, "ihx", 1);
  337. #else /* SDK */
  338.                 ofp = afile(linkp->f_idp, "IHX", 1);
  339. #endif /* SDK */
  340.                 if (ofp == NULL) {
  341.                     lkexit(1);
  342.                 }
  343.             } else
  344.             if (oflag == 2) {
  345. #ifdef SDK
  346.                 ofp = afile(linkp->f_idp, "s19", 1);
  347. #else /* SDK */
  348.                 ofp = afile(linkp->f_idp, "S19", 1);
  349. #endif /* SDK */
  350.                 if (ofp == NULL) {
  351.                     lkexit(1);
  352.                 }
  353. #ifdef SDK
  354.             } else
  355.             if (oflag == 3) {
  356.                 binary = 1;
  357.                 ofp = afile(linkp->f_idp, "", 1);
  358.                 binary = 0;
  359.                 if (ofp == NULL) {
  360.                     lkexit(1);
  361.                 }
  362. #endif /* SDK */
  363.             }
  364.         } else {
  365.             /*
  366.              * Link in library files
  367.              */
  368.             library();
  369.             reloc('E');
  370.         }
  371.     }
  372.     lkexit(lkerr);
  373. }
  374.  
  375. /*)Function    VOID    lkexit(i)
  376.  *
  377.  *            int    i    exit code
  378.  *
  379.  *    The function lkexit() explicitly closes all open
  380.  *    files and then terminates the program.
  381.  *
  382.  *    local variables:
  383.  *        none
  384.  *
  385.  *    global variables:
  386.  *        FILE *    mfp        file handle for .map
  387.  *        FILE *    ofp        file handle for .ihx/.s19
  388.  *        FILE *    rfp        file hanlde for .rst
  389.  *        FILE *    sfp        file handle for .rel
  390.  *        FILE *    tfp        file handle for .lst
  391.  *
  392.  *    functions called:
  393.  *        int    fclose()    c_library
  394.  *        VOID    exit()        c_library
  395.  *
  396.  *    side effects:
  397.  *        All files closed. Program terminates.
  398.  */
  399.  
  400. VOID 
  401. lkexit(i)
  402. int i;
  403. {
  404.     if (mfp != NULL) fclose(mfp);
  405.     if (ofp != NULL) fclose(ofp);
  406.     if (rfp != NULL) fclose(rfp);
  407.     if (sfp != NULL) fclose(sfp);
  408.     if (tfp != NULL) fclose(tfp);
  409.     exit(i);
  410. }
  411.  
  412. /*)Function    link()
  413.  *
  414.  *    The function link() evaluates the directives for each line of
  415.  *    text read from the .rel file(s).  The valid directives processed
  416.  *    are:
  417.  *        X, D, Q, H, M, A, S, T, R, and P.
  418.  *
  419.  *    local variables:
  420.  *        int    c        first non blank character of a line
  421.  *
  422.  *    global variables:
  423.  *        head    *headp        The pointer to the first
  424.  *                     head structure of a linked list
  425.  *        head    *hp        Pointer to the current
  426.  *                     head structure
  427.  *        int    pass        linker pass number
  428.  *        int    radix        current number conversion radix
  429.  *
  430.  *    functions called:
  431.  *        char    endline()    lklex.c
  432.  *        VOID    module()    lkhead.c
  433.  *        VOID    newarea()    lkarea.c
  434.  *        VOID    newhead()    lkhead.c
  435.  *        sym *    newsym()    lksym.c
  436.  *        VOID    reloc()        lkreloc.c
  437.  *
  438.  *    side effects:
  439.  *        Head, area, and symbol structures are created and
  440.  *        the radix is set as the .rel file(s) are read.
  441.  */
  442.  
  443. VOID
  444. link()
  445. {
  446.     register c;
  447.  
  448.     if ((c=endline()) == 0) { return; }
  449.     switch (c) {
  450.  
  451.     case 'X':
  452.         radix = 16;
  453.         break;
  454.  
  455.     case 'D':
  456.         radix = 10;
  457.         break;
  458.  
  459.     case 'Q':
  460.         radix = 8;
  461.         break;
  462.  
  463.     case 'H':
  464.         if (pass == 0) {
  465.             newhead();
  466.         } else {
  467.             if (hp == 0) {
  468.                 hp = headp;
  469.             } else {
  470.                 hp = hp->h_hp;
  471.             }
  472.         }
  473.         sdp.s_area = NULL;
  474.         sdp.s_areax = NULL;
  475.         sdp.s_addr = 0;
  476.         break;
  477.  
  478.     case 'M':
  479.         if (pass == 0)
  480.             module();
  481.         break;
  482.  
  483.     case 'A':
  484.         if (pass == 0)
  485.             newarea();
  486.         if (sdp.s_area == NULL) {
  487.             sdp.s_area = areap;
  488.             sdp.s_areax = areap->a_axp;
  489.             sdp.s_addr = 0;
  490.         }
  491.         break;
  492.  
  493.     case 'S':
  494.         if (pass == 0)
  495.             newsym();
  496.         break;
  497.  
  498.     case 'T':
  499.     case 'R':
  500.     case 'P':
  501.         if (pass == 0)
  502.             break;
  503.         reloc(c);
  504.         break;
  505.  
  506.     default:
  507.         break;
  508.     }
  509.     if (c == 'X' || c == 'D' || c == 'Q') {
  510.         if ((c = get()) == 'H') {
  511.             hilo = 1;
  512.         } else
  513.         if (c == 'L') {
  514.             hilo = 0;
  515.         }
  516.     }
  517. }
  518.  
  519. /*)Function    VOID    map()
  520.  *
  521.  *    The function map() opens the output map file and calls the various
  522.  *    routines to
  523.  *    (1) output the variables in each area,
  524.  *    (2) list the files processed with module names,
  525.  *    (3) list the libraries file processed,
  526.  *    (4) list base address definitions,
  527.  *    (5) list global variable definitions, and
  528.  *    (6) list any undefined variables.
  529.  *
  530.  *    local variables:
  531.  *        int     i        counter
  532.  *        head *    hdp        pointer to head structure
  533.  *        lbfile *lbfh        pointer to library file structure
  534.  *
  535.  *    global variables:
  536.  *        area    *ap        Pointer to the current
  537.  *                     area structure
  538.  *        area    *areap        The pointer to the first
  539.  *                     area structure of a linked list
  540.  *        base    *basep        The pointer to the first
  541.  *                     base structure
  542.  *        base    *bsp        Pointer to the current
  543.  *                     base structure
  544.  *        lfile    *filep         The pointer *filep points to the
  545.  *                     beginning of a linked list of
  546.  *                     lfile structures.
  547.  *        globl    *globlp        The pointer to the first
  548.  *                     globl structure
  549.  *        globl    *gsp        Pointer to the current
  550.  *                     globl structure
  551.  *        head    *headp        The pointer to the first
  552.  *                     head structure of a linked list
  553.  *        lbfile    *lbfhead    The pointer to the first
  554.  *                    lbfile structure of a linked list
  555.  *        lfile    *linkp        pointer to first lfile structure
  556.  *                     containing an input REL file
  557.  *                     specification
  558.  *        int    lop        current line number on page
  559.  *        FILE    *mfp        Map output file handle
  560.  *        int    page        current page number
  561.  *
  562.  *    functions called:
  563.  *        FILE *    afile()        lkmain.c
  564.  *        int    fprintf()    c_library
  565.  *        VOID    lkexit()    lkmain.c
  566.  *        VOID    lstarea()    lklist.c
  567.  *        VOID    newpag()    lklist.c
  568.  *        VOID    symdef()    lksym.c
  569.  *
  570.  *    side effects:
  571.  *        The map file is created.
  572.  */
  573.  
  574. #ifndef MLH_MAP
  575. VOID
  576. map()
  577. {
  578.     register i;
  579.     register struct head *hdp;
  580.     register struct lbfile *lbfh;
  581.  
  582.     /*
  583.      * Open Map File
  584.      */
  585. #ifdef SDK
  586.     mfp = afile(linkp->f_idp, "map", 1);
  587. #else /* SDK */
  588.     mfp = afile(linkp->f_idp, "MAP", 1);
  589. #endif /* SDK */
  590.     if (mfp == NULL) {
  591.         lkexit(1);
  592.     }
  593.  
  594.     /*
  595.      * Output Map Area Lists
  596.      */
  597.     page = 0;
  598.     lop  = NLPP;
  599.     ap = areap;
  600.     while (ap) {
  601.         lstarea(ap);
  602.         ap = ap->a_ap;
  603.     }
  604.     /*
  605.      * List Linked Files
  606.      */
  607.     newpag(mfp);
  608.     fprintf(mfp, "\nFiles Linked      [ module(s) ]\n\n");
  609.     hdp = headp;
  610. #ifdef SDK
  611.     filep = linkp->f_flp;
  612. #else /* SDK */
  613.     filep = linkp;
  614. #endif /* SDK */
  615.     while (filep) {
  616.         fprintf(mfp, "%-16s", filep->f_idp);
  617.         i = 0;
  618.         while ((hdp != NULL) && (hdp->h_lfile == filep)) {
  619.             if (i % 5) {
  620.                 fprintf(mfp, ", %8.8s", hdp->m_id);
  621.             } else {
  622.                 if (i) {
  623.                 fprintf(mfp, ",\n%20s%8.8s", "", hdp->m_id);
  624.                 } else {
  625.                 fprintf(mfp, "  [ %8.8s", hdp->m_id);
  626.                 }
  627.             }
  628.             hdp = hdp->h_hp;
  629.             i++;
  630.         }
  631.         if (i)
  632.             fprintf(mfp, " ]");
  633.         fprintf(mfp, "\n");
  634.         filep = filep->f_flp;
  635.     }
  636.     /*
  637.      * List Linked Libraries
  638.      */
  639.     if (lbfhead != NULL) {
  640.         fprintf(mfp,
  641.     "\nLibraries Linked                    [   object  file   ]\n\n");
  642.         for (lbfh=lbfhead; lbfh; lbfh=lbfh->next) {
  643.             fprintf(mfp, "%-32s    [ %16.16s ]\n",
  644.                 lbfh->libspc, lbfh->relfil);
  645.         }
  646.         fprintf(mfp, "\n");
  647.     }
  648.     /*
  649.      * List Base Address Definitions
  650.      */
  651.     if (basep) {
  652.         newpag(mfp);
  653.         fprintf(mfp, "\nUser Base Address Definitions\n\n");
  654.         bsp = basep;
  655.         while (bsp) {
  656.             fprintf(mfp, "%s\n", bsp->b_strp);
  657.             bsp = bsp->b_base;
  658.         }
  659.     }
  660.     /*
  661.      * List Global Definitions
  662.      */
  663.     if (globlp) {
  664.         newpag(mfp);
  665.         fprintf(mfp, "\nUser Global Definitions\n\n");
  666.         gsp = globlp;
  667.         while (gsp) {
  668.             fprintf(mfp, "%s\n", gsp->g_strp);
  669.             gsp = gsp->g_globl;
  670.         }
  671.     }
  672.     fprintf(mfp, "\n\f");
  673.     symdef(mfp);
  674. }
  675. #else
  676. VOID map()
  677. {
  678.     register i;
  679.     register struct head *hdp;
  680.     register struct lbfile *lbfh;
  681.  
  682.     /*
  683.      * Open Map File
  684.      */
  685. #ifdef SDK
  686.     mfp = afile(linkp->f_idp, "map", 1);
  687. #else /* SDK */
  688.     mfp = afile(linkp->f_idp, "MAP", 1);
  689. #endif /* SDK */
  690.     if (mfp == NULL) {
  691.         lkexit(1);
  692.     }
  693.  
  694.     /*
  695.      *Output Map Area Lists
  696.      */
  697.     page = 0;
  698.     lop  = NLPP;
  699.     ap = areap;
  700.     while (ap) {
  701.         lstarea(ap);
  702.         ap = ap->a_ap;
  703.     }
  704.     /*
  705.      * List Linked Files
  706.      */
  707.     hdp = headp;
  708. #ifdef SDK
  709.     filep = linkp->f_flp;
  710. #else /* SDK */
  711.     filep = linkp;
  712. #endif /* SDK */
  713.     if (filep) {
  714.         fprintf( mfp, "MODULES\n");
  715.     }
  716.     while (filep) {
  717.         fprintf(mfp, "\tFILE %s\n", filep->f_idp);
  718.         while ((hdp != NULL) && (hdp->h_lfile == filep)) {
  719.             if (strlen(hdp->m_id)>0)
  720.                 fprintf(mfp, "\t\tNAME %s\n", hdp->m_id);
  721.             hdp = hdp->h_hp;
  722.         }
  723.         filep = filep->f_flp;
  724.     }
  725.     /*
  726.      * List Linked Libraries
  727.      */
  728.     if (lbfhead != NULL) {
  729.         fprintf(mfp, "LIBRARIES\n");
  730.         for (lbfh=lbfhead; lbfh; lbfh=lbfh->next) {
  731.             fprintf(mfp,    "\tLIBRARY %s\n"
  732.                     "\t\tMODULE %s\n",
  733.                 lbfh->libspc, lbfh->relfil);
  734.         }
  735.     }
  736.     /*
  737.      * List Base Address Definitions
  738.      */
  739.     if (basep) {
  740.         fprintf(mfp, "USERBASEDEF\n");
  741.         bsp = basep;
  742.         while (bsp) {
  743.             fprintf(mfp, "\t%s\n", bsp->b_strp);
  744.             bsp = bsp->b_base;
  745.         }
  746.     }
  747.     /*
  748.      * List Global Definitions
  749.      */
  750.     if (globlp) {
  751.         fprintf(mfp, "USERGLOBALDEF\n");
  752.         gsp = globlp;
  753.         while (gsp) {
  754.             fprintf(mfp, "\t%s\n", gsp->g_strp);
  755.             gsp = gsp->g_globl;
  756.         }
  757.     }
  758.     symdef(mfp);
  759. #ifdef SDK
  760.     if (mfp!=NULL) {
  761.         fclose(mfp);
  762.     }
  763. #endif
  764. }
  765. #endif /* MLH_MAP */
  766.  
  767. #ifdef SDK
  768. VOID sym()
  769. {
  770.     register i;
  771.     register struct head *hdp;
  772.     register struct lbfile *lbfh;
  773.  
  774.     /*
  775.      * Open sym File
  776.      */
  777.     mfp = afile(linkp->f_idp, "sym", 1);
  778.     if (mfp == NULL) {
  779.         lkexit(1);
  780.     }
  781. #ifdef AMIGA
  782.     fprintf( mfp,    "; no$gmb format .sym file\n"
  783.             "; Generated automagically by ASxxxx linker %s\n"
  784.         , VERSION );
  785. #else
  786.     fprintf( mfp,    "; no$gmb format .sym file\n"
  787.             "; Generated automagically by ASxxxx linker %s (SDK " SDK_VERSION_STRING ")\n"
  788.         , VERSION );
  789. #endif
  790.     /*
  791.      * Output sym Area Lists
  792.      */
  793.     page = 0;
  794.     lop  = NLPP;
  795.     ap = areap;
  796.     while (ap) {
  797.         lstareatosym(ap);
  798.         ap = ap->a_ap;
  799.     }
  800.     if (mfp!=NULL) {
  801.         fclose(mfp);
  802.     }
  803. }
  804. #endif /* SDK */
  805.  
  806. /*)Function    int    parse()
  807.  *
  808.  *    The function parse() evaluates all command line or file input
  809.  *    linker directives and updates the appropriate variables.
  810.  *
  811.  *    local variables:
  812.  *        int    c        character value
  813.  *        char    fid[]        file id string
  814.  *
  815.  *    global variables:
  816.  *        char    ctype[]        array of character types, one per
  817.  *                     ASCII character
  818.  *        lfile    *lfp        pointer to current lfile structure
  819.  *                     being processed by parse()
  820.  *        lfile    *linkp        pointer to first lfile structure
  821.  *                     containing an input REL file
  822.  *                     specification
  823.  *        int    mflag        Map output flag
  824.  *        int    oflag        Output file type flag
  825.  *        int    pflag        print linker command file flag
  826.  *        FILE *    stderr        c_library
  827.  *        int    uflag        Relocated listing flag
  828.  *        int    xflag        Map file radix type flag
  829.  *
  830.  *    Functions called:
  831.  *        VOID    addlib()    lklibr.c
  832.  *        VOID    addpath()    lklibr.c
  833.  *        VOID    bassav()    lkmain.c
  834.  *        int    fprintf()    c_library
  835.  *        VOID    gblsav()    lkmain.c
  836.  *        VOID    getfid()    lklex.c
  837.  *        char    getnb()        lklex.c
  838.  *        VOID    lkexit()    lkmain.c
  839.  *        char *    strcpy()    c_library
  840.  *        int    strlen()    c_library
  841.  *
  842.  *    side effects:
  843.  *        Various linker flags are updated and the linked
  844.  *        structure lfile is created.
  845.  */
  846.  
  847. int
  848. parse()
  849. {
  850.     register c;
  851.     char fid[NINPUT];
  852.  
  853.     while ((c = getnb()) != 0) {
  854.         if ( c == '-') {
  855.             while (ctype[c=get()] & LETTER) {
  856.                 switch(c) {
  857.  
  858.                 case 'i':
  859.                 case 'I':
  860.                     oflag = 1;
  861.                     break;
  862.  
  863.                 case 's':
  864.                 case 'S':
  865.                     oflag = 2;
  866.                     break;
  867. #ifdef GAMEBOY
  868.                 case 'y':
  869.                 case 'Y':
  870.                     c = get();
  871.                     if(c == 'O' || c == 'o')
  872.                         nb_rom_banks = expr(0);
  873.                     else if(c == 'A' || c == 'a')
  874.                         nb_ram_banks = expr(0);
  875.                     else if(c == 'T' || c == 't')
  876.                         mbc_type = expr(0);
  877.                     else if(c == 'N' || c == 'n') {
  878.                         int i = 0;
  879.                         if(getnb() != '=' || getnb() != '"') {
  880.                             fprintf(stderr, "Syntax error in -YN=\"name\" flag\n");
  881.                             lkexit(1);
  882.                         }
  883.                         while((c = get()) != '"' && i < 16) {
  884.                             cart_name[i++] = c;
  885.                         }
  886.                         if(i < 16)
  887.                             cart_name[i] = 0;
  888.                         else
  889.                             while(get() != '"')
  890.                                 ;
  891.                     } else if(c == 'P' || c == 'p') {
  892.                         unsigned int addr;
  893.                         unsigned char value;
  894.                         patch *p = patches;
  895.  
  896.                         patches = (patch *)malloc(sizeof(patch));
  897.                         patches->next = p;
  898.                         patches->addr = expr(0);
  899.                         if(getnb() != '=') {
  900.                             fprintf(stderr, "Syntax error in -YHaddr=val flag\n");
  901.                             lkexit(1);
  902.                         }
  903.                         patches->value = expr(0);
  904.                     } else {
  905.                         fprintf(stderr, "Invalid option\n");
  906.                         lkexit(1);
  907.                     }
  908.                     break;
  909.  
  910.                 case 'z':
  911.                 case 'Z':
  912.                     oflag = 3;
  913.                     break;
  914.                 case 'j':
  915.                 case 'J':
  916.                     ++symflag;
  917.                     break;
  918. #endif /* GAMEBOY */
  919.  
  920.                 case 'm':
  921.                 case 'M':
  922.                     ++mflag;
  923.                     break;
  924.  
  925.                 case 'u':
  926.                 case 'U':
  927.                     uflag = 1;
  928.                     break;
  929.  
  930.                 case 'x':
  931.                 case 'X':
  932.                     xflag = 0;
  933.                     break;
  934.  
  935.                 case 'q':
  936.                 case 'Q':
  937.                     xflag = 1;
  938.                     break;
  939.  
  940.                 case 'd':
  941.                 case 'D':
  942.                     xflag = 2;
  943.                     break;
  944.  
  945.                 case 'e':
  946.                 case 'E':
  947.                     return(1);
  948.  
  949.                 case 'n':
  950.                 case 'N':
  951.                     pflag = 0;
  952.                     break;
  953.  
  954.                 case 'p':
  955.                 case 'P':
  956.                     pflag = 1;
  957.                     break;
  958.  
  959.                 case 'b':
  960.                 case 'B':
  961.                     bassav();
  962.                     return(0);
  963.  
  964.                 case 'g':
  965.                 case 'G':
  966.                     gblsav();
  967.                     return(0);
  968.  
  969.                 case 'k':
  970.                 case 'K':
  971.                     addpath();
  972.                     return(0);
  973.  
  974.                 case 'l':
  975.                 case 'L':
  976.                     addlib();
  977.                     return(0);
  978.  
  979.                 default:
  980.                     fprintf(stderr, "Invalid option\n");
  981.                     lkexit(1);
  982.                 }
  983.             }
  984.         } else
  985.         if (ctype[c] != ILL) {
  986.             if (linkp == NULL) {
  987.                 linkp = (struct lfile *)
  988.                     new (sizeof (struct lfile));
  989.                 lfp = linkp;
  990.             } else {
  991.                 lfp->f_flp = (struct lfile *)
  992.                         new (sizeof (struct lfile));
  993.                 lfp = lfp->f_flp;
  994.             }
  995.             getfid(fid, c);
  996.             lfp->f_idp = (char *) new (strlen(fid)+1);
  997.             strcpy(lfp->f_idp, fid);
  998.             lfp->f_type = F_REL;
  999.         } else {
  1000.             fprintf(stderr, "Invalid input");
  1001.             lkexit(1);
  1002.         }
  1003.     }
  1004.     return(0);
  1005. }
  1006.  
  1007. /*)Function    VOID    bassav()
  1008.  *
  1009.  *    The function bassav() creates a linked structure containing
  1010.  *    the base address strings input to the linker.
  1011.  *
  1012.  *    local variables:
  1013.  *        none
  1014.  *
  1015.  *    global variables:
  1016.  *        base    *basep        The pointer to the first
  1017.  *                     base structure
  1018.  *        base    *bsp        Pointer to the current
  1019.  *                     base structure
  1020.  *        char    *ip        pointer into the REL file
  1021.  *                     text line in ib[]
  1022.  *
  1023.  *     functions called:
  1024.  *        char    getnb()        lklex.c
  1025.  *        VOID *    new()        lksym.c
  1026.  *        int    strlen()    c_library
  1027.  *        char *    strcpy()    c_library
  1028.  *        VOID    unget()        lklex.c
  1029.  *
  1030.  *    side effects:
  1031.  *        The basep structure is created.
  1032.  */
  1033.  
  1034. VOID
  1035. bassav()
  1036. {
  1037.     if (basep == NULL) {
  1038.         basep = (struct base *)
  1039.             new (sizeof (struct base));
  1040.         bsp = basep;
  1041.     } else {
  1042.         bsp->b_base = (struct base *)
  1043.                 new (sizeof (struct base));
  1044.         bsp = bsp->b_base;
  1045.     }
  1046.     unget(getnb());
  1047.     bsp->b_strp = (char *) new (strlen(ip)+1);
  1048.     strcpy(bsp->b_strp, ip);
  1049. }
  1050.     
  1051. /*)Function    VOID    setbas()
  1052.  *
  1053.  *    The function setbas() scans the base address lines in hte
  1054.  *    basep structure, evaluates the arguments, and sets beginning
  1055.  *    address of the specified areas.
  1056.  *
  1057.  *    local variables:
  1058.  *        int    v        expression value
  1059.  *        char    id[]        base id string
  1060.  *
  1061.  *    global variables:
  1062.  *        area    *ap        Pointer to the current
  1063.  *                     area structure
  1064.  *        area    *areap        The pointer to the first
  1065.  *                     area structure of a linked list
  1066.  *        base    *basep        The pointer to the first
  1067.  *                     base structure
  1068.  *        base    *bsp        Pointer to the current
  1069.  *                     base structure
  1070.  *        char    *ip        pointer into the REL file
  1071.  *                     text line in ib[]
  1072.  *        int    lkerr        error flag
  1073.  *
  1074.  *     functions called:
  1075.  *        addr_t    expr()        lkeval.c
  1076.  *        int    fprintf()    c_library
  1077.  *        VOID    getid()        lklex.c
  1078.  *        char    getnb()        lklex.c
  1079.  *        int    symeq()        lksym.c
  1080.  *
  1081.  *    side effects:
  1082.  *        The base address of an area is set.
  1083.  */
  1084.  
  1085. VOID
  1086. setbas()
  1087. {
  1088.     register v;
  1089.     char id[NCPS];
  1090.  
  1091.     bsp = basep;
  1092.     while (bsp) {
  1093.         ip = bsp->b_strp;
  1094.         getid(id, -1);
  1095.         if (getnb() == '=') {
  1096.             v = expr(0);
  1097.             for (ap = areap; ap != NULL; ap = ap->a_ap) {
  1098.                 if (symeq(id, ap->a_id))
  1099.                     break;
  1100.             }
  1101.             if (ap == NULL) {
  1102. #ifndef SDK
  1103.                 fprintf(stderr,
  1104.                 "No definition of area %s\n", id);
  1105.                 lkerr++;
  1106. #endif /* SDK */
  1107.             } else {
  1108.                 ap->a_addr = v;
  1109.             }
  1110.         } else {
  1111.             fprintf(stderr, "No '=' in base expression");
  1112.             lkerr++;
  1113.         }
  1114.         bsp = bsp->b_base;
  1115.     }
  1116. }
  1117.  
  1118. /*)Function    VOID    gblsav()
  1119.  *
  1120.  *    The function gblsav() creates a linked structure containing
  1121.  *    the global variable strings input to the linker.
  1122.  *
  1123.  *    local variable:
  1124.  *        none
  1125.  *
  1126.  *    global variables:
  1127.  *        globl    *globlp        The pointer to the first
  1128.  *                     globl structure
  1129.  *        globl    *gsp        Pointer to the current
  1130.  *                     globl structure
  1131.  *        char    *ip        pointer into the REL file
  1132.  *                     text line in ib[]
  1133.  *        int    lkerr        error flag
  1134.  *
  1135.  *    functions called:
  1136.  *        char    getnb()        lklex.c
  1137.  *        VOID *    new()        lksym.c
  1138.  *        int    strlen()    c_library
  1139.  *        char *    strcpy()    c_library
  1140.  *        VOID    unget()        lklex.c
  1141.  *
  1142.  *    side effects:
  1143.  *        The globlp structure is created.
  1144.  */
  1145.  
  1146. VOID
  1147. gblsav()
  1148. {
  1149.     if (globlp == NULL) {
  1150.         globlp = (struct globl *)
  1151.             new (sizeof (struct globl));
  1152.         gsp = globlp;
  1153.     } else {
  1154.         gsp->g_globl = (struct globl *)
  1155.                 new (sizeof (struct globl));
  1156.         gsp = gsp->g_globl;
  1157.     }
  1158.     unget(getnb());
  1159.     gsp->g_strp = (char *) new (strlen(ip)+1);
  1160.     strcpy(gsp->g_strp, ip);
  1161. }
  1162.     
  1163. /*)Function    VOID    setgbl()
  1164.  *
  1165.  *    The function setgbl() scans the global variable lines in hte
  1166.  *    globlp structure, evaluates the arguments, and sets a variable
  1167.  *    to this value.
  1168.  *
  1169.  *    local variables:
  1170.  *        int    v        expression value
  1171.  *        char    id[]        base id string
  1172.  *        sym *    sp        pointer to a symbol structure
  1173.  *
  1174.  *    global variables:
  1175.  *        char    *ip        pointer into the REL file
  1176.  *                     text line in ib[]
  1177.  *        globl    *globlp        The pointer to the first
  1178.  *                     globl structure
  1179.  *        globl    *gsp        Pointer to the current
  1180.  *                     globl structure
  1181.  *        FILE *    stderr        c_library
  1182.  *        int    lkerr        error flag
  1183.  *
  1184.  *     functions called:
  1185.  *        addr_t    expr()        lkeval.c
  1186.  *        int    fprintf()    c_library
  1187.  *        VOID    getid()        lklex.c
  1188.  *        char    getnb()        lklex.c
  1189.  *        sym *    lkpsym()    lksym.c
  1190.  *
  1191.  *    side effects:
  1192.  *        The value of a variable is set.
  1193.  */
  1194.  
  1195. VOID
  1196. setgbl()
  1197. {
  1198.     register v;
  1199.     register struct sym *sp;
  1200.     char id[NCPS];
  1201.  
  1202.     gsp = globlp;
  1203.     while (gsp) {
  1204.         ip = gsp->g_strp;
  1205.         getid(id, -1);
  1206.         if (getnb() == '=') {
  1207.             v = expr(0);
  1208.             sp = lkpsym(id, 0);
  1209.             if (sp == NULL) {
  1210. #ifndef SDK
  1211.                 fprintf(stderr,
  1212.                 "No definition of symbol %s\n", id);
  1213.                 lkerr++;
  1214. #endif /* SDK */
  1215.             } else {
  1216. #ifndef SDK
  1217.                 if (sp->s_flag & S_DEF) {
  1218.                     fprintf(stderr,
  1219.                     "Redefinition of symbol %s\n", id);
  1220.                     lkerr++;
  1221.                     sp->s_axp = NULL;
  1222.                 }
  1223. #endif /* SDK */
  1224.                 sp->s_addr = v;
  1225.                 sp->s_type |= S_DEF;
  1226.             }
  1227.         } else {
  1228.             fprintf(stderr, "No '=' in global expression");
  1229.             lkerr++;
  1230.         }
  1231.         gsp = gsp->g_globl;
  1232.     }
  1233. }
  1234.  
  1235. /*)Function    FILE *    afile(fn,, ft, wf)
  1236.  *
  1237.  *        char *    fn        file specification string
  1238.  *        char *    ft        file type string
  1239.  *        int    wf        read(0)/write(1) flag
  1240.  *
  1241.  *    The function afile() opens a file for reading or writing.
  1242.  *        (1)    If the file type specification string ft
  1243.  *            is not NULL then a file specification is
  1244.  *            constructed with the file path\name in fn
  1245.  *            and the extension in ft.
  1246.  *        (2)    If the file type specification string ft
  1247.  *            is NULL then the file specification is
  1248.  *            constructed from fn.  If fn does not have
  1249.  *            a file type then the default .rel file
  1250.  *            type is appended to the file specification.
  1251.  *
  1252.  *    afile() returns a file handle for the opened file or aborts
  1253.  *    the assembler on an open error.
  1254.  *
  1255.  *    local variables:
  1256.  *        int    c        character value
  1257.  *        char    fb[]        constructed file specification string
  1258.  *        FILE *    fp        filehandle for opened file
  1259.  *        char *    p1        pointer to filespec string fn
  1260.  *        char *    p2        pointer to filespec string fb
  1261.  *        char *    p3        pointer to filetype string ft
  1262.  *
  1263.  *    global variables:
  1264.  *        int    lkerr        error flag
  1265.  *
  1266.  *    functions called:
  1267.  *        FILE *    fopen()        c_library
  1268.  *        int    fprintf()    c_library
  1269.  *
  1270.  *    side effects:
  1271.  *        File is opened for read or write.
  1272.  */
  1273.  
  1274. FILE *
  1275. afile(char *fn,char *ft,int wf)
  1276. {
  1277.     register char *p1, *p2, *p3;
  1278.     register c;
  1279.     FILE *fp;
  1280.     char fb[FILSPC];
  1281.  
  1282.     p1 = fn;
  1283.     p2 = fb;
  1284.     p3 = ft;
  1285.     while ((c = *p1++) != 0 && c != FSEPX) {
  1286.         if (p2 < &fb[FILSPC-4])
  1287.             *p2++ = c;
  1288.     }
  1289.     *p2++ = FSEPX;
  1290.     if (*p3 == 0) {
  1291.         if (c == FSEPX) {
  1292.             p3 = p1;
  1293.         } else {
  1294. #ifdef SDK
  1295.             p3 = "rel";
  1296. #else /* SDK */
  1297.             p3 = "REL";
  1298. #endif /* SDK */
  1299.         }
  1300.     }
  1301.     while ((c = *p3++) != 0) {
  1302.         if (p2 < &fb[FILSPC-1])
  1303.             *p2++ = c;
  1304.     }
  1305.     *p2++ = 0;
  1306. #ifdef SDK
  1307.     if ((fp = fopen(fb, wf?(binary?"wb":"w"):(binary?"rb":"r"))) == NULL) {
  1308. #else /* SDK */
  1309.     if ((fp = fopen(fb, wf?"w":"r")) == NULL) {
  1310. #endif /* SDK */
  1311.         fprintf(stderr, "%s: cannot %s.\n", fb, wf?"create":"open");
  1312.         lkerr++;
  1313.     }
  1314.     return (fp);
  1315. }
  1316.  
  1317. char *usetxt[] = {
  1318. /*
  1319. #ifdef SDK
  1320.     "Distributed with SDK " SDK_VERSION_STRING ", built on " __DATE__ " " __TIME__,
  1321.     "Compile options: SDK Target " TARGET_STRING
  1322. #ifdef INDEXLIB
  1323.     " INDEXLIB"
  1324. #endif
  1325.     "\n",
  1326. #endif
  1327. */
  1328.     "Startup:",
  1329. #ifdef SDK
  1330.     "  --   [Commands]              Non-interactive command line input",
  1331. #endif /* SDK */
  1332.     "  -c                           Command line input",
  1333.     "  -f   file[LNK]               File input",
  1334.     "  -p   Prompt and echo of file[LNK] to stdout (default)",
  1335.     "  -n   No echo of file[LNK] to stdout",
  1336. #ifdef SDK
  1337.     "Usage: [-Options] outfile file [file ...]",
  1338. #else /* SDK */
  1339.     "Usage: [-Options] file [file ...]",
  1340. #endif /* SDK */
  1341.     "Librarys:",
  1342.     "  -k    Library path specification, one per -k",
  1343.     "  -l    Library file specification, one per -l",
  1344.     "Relocation:",
  1345.     "  -b   area base address = expression",
  1346.     "  -g   global symbol = expression",
  1347. #ifdef GAMEBOY
  1348.     "  -yo  Number of rom banks (default: 2)",
  1349.     "  -ya  Number of ram banks (default: 0)",
  1350.     "  -yt  MBC type (default: no MBC)",
  1351.     "  -yn  Name of program (default: name of output file)",
  1352.     "  -yp# Patch one byte in the output GB file (# is: addr=byte)",
  1353. #endif /* GAMEBOY */
  1354.     "Map format:",
  1355.     "  -m   Map output generated as file[MAP]",
  1356. #ifdef GAMEBOY
  1357.     "  -j   no$gmb symbol file generated as file[SYM]",
  1358. #endif /* GAMEBOY */
  1359.     "  -x   Hexidecimal (default)",
  1360.     "  -d   Decimal",
  1361.     "  -q   Octal",
  1362.     "Output:",
  1363.     "  -i   Intel Hex as file[IHX]",
  1364.     "  -s   Motorola S19 as file[S19]",
  1365. #ifdef GAMEBOY
  1366.     "  -z   Gameboy image as file[GB]",
  1367. #endif /* GAMEBOY */
  1368.     "List:",
  1369.     "  -u    Update listing file(s) with link data as file(s)[.RST]",
  1370.     "End:",
  1371.     "  -e   or null line terminates input",
  1372.     "",
  1373.     0
  1374. };
  1375.  
  1376. /*)Function    VOID    usage()
  1377.  *
  1378.  *    The function usage() outputs to the stderr device the
  1379.  *    assembler name and version and a list of valid assembler options.
  1380.  *
  1381.  *    local variables:
  1382.  *        char **    dp        pointer to an array of
  1383.  *                    text string pointers.
  1384.  *
  1385.  *    global variables:
  1386.  *        FILE *    stderr        c_library
  1387.  *
  1388.  *    functions called:
  1389.  *        int    fprintf()    c_library
  1390.  *
  1391.  *    side effects:
  1392.  *        none
  1393.  */
  1394.  
  1395. VOID
  1396. usage()
  1397. {
  1398.     register char    **dp;
  1399.  
  1400.     fprintf(stderr, "\nASxxxx Linker %s\n\n", VERSION);
  1401.     for (dp = usetxt; *dp; dp++)
  1402.         fprintf(stderr, "%s\n", *dp);
  1403.     lkexit(1);
  1404. }
  1405.